//
//  GameBase.c
//  SnakeGame
//
//  Created by Hansuck Shim on 2014. 3. 9..
//  Copyright (c) 2014년 Hansuck Shim. All rights reserved.
//

#include "GameBase.h"

#include <stdio.h>  // debug & NULL
#include <stdlib.h> // system("clear")
#include <sys/time.h>

#include "Map.h"
#include "SnakeBody.h"
#include "MyKeyboard.h"

int g_nGameState;
struct timeval g_kLastTime;

void InitGameBase(void)
{
    g_pSnake = NULL;
    // set dir right
    g_nHeadDirX = 1;
    g_nHeadDirY = 0;
    g_nKeyDirX = 1;
    g_nKeyDirY = 0;

    // first node
    AppendSnakeBody(AllocSnakeBody());
    if( g_pSnake == NULL )
        return;
    g_pSnake->nX = 2;
    g_pSnake->nY = 2;

    // second node
    AppendSnakeBody(AllocSnakeBody());
    if( g_pSnake->pNext == NULL )
    {
        free( g_pSnake );
        g_pSnake = NULL;
        return;
    }
    g_pSnake->pNext->nX = 1;
    g_pSnake->pNext->nY = 2;
    
    g_nGameState = GAME_STATE_PLAY;
    gettimeofday(&g_kLastTime, NULL);
    
    SetKeyRawMode();
    
    srand(time(NULL));
    NewFood();
}

void TermGameBase(void)
{
    if( g_pSnake != NULL )
    {
        ResetSnakeBody(0);
        g_pSnake = NULL;
    }
}

void UpdateGameBase(void)
{
    switch( CheckSnakeMovable() )
    {
        case SNAKE_UNMOVABLE:
            g_nGameState = GAME_STATE_STOP;
            break;
        case SNAKE_MOVABLE_FOOD:
        {
            if( GetSnakeLength() > 5 )
            {
                g_nGameState = GAME_STATE_STOP;
                break;
            }
            
            g_arrGameMap[(g_pSnake->nY + g_nHeadDirY)][(g_pSnake->nX + g_nHeadDirX)] = 0;
            AppendSnakeBody( AllocSnakeBody() );
            MoveSnake();
            NewFood();
        }
            break;
        case SNAKE_MOVABLE_EMPTY:
            MoveSnake();
            break;
        default:
            printf("Unknown return value from CheckSnakeMovable()\r\n");
            break;
    }
}

void DrawGameBase(void)
{
    system("clear");
    
    // read map and draw things
    int width;
    int height;
    
    for( height = 0; height < MAX_HEIGHT; ++height )
    {
        for( width = 0; width < MAX_WIDTH; ++width )
        {
            if( IsSnakeThere(width, height) == SNAKE_IS_THERE )
                printf("@");
            else
            {
                switch( g_arrGameMap[height][width] )
                {
                    case 0:     // empty space
                        printf(" ");
                        break;
                    case 1:     // wall
                        printf("#");
                        break;
                    case 2:     // food
                        printf("$");
                        break;
                    default:
                        printf("?");
                        break;
                }
            }
        }
        
        printf("\r\n");
    }
}

int IsTimeToUpdate(void)
{
    struct timeval kCurrentTime;
    gettimeofday(&kCurrentTime, NULL);
    
    long long int nCurrentMillisec = (kCurrentTime.tv_sec * 1000) + (kCurrentTime.tv_usec / 1000);
    long long int nLastMillisec = (g_kLastTime.tv_sec * 1000) + (g_kLastTime.tv_usec / 1000);
    
    if( nCurrentMillisec - nLastMillisec > 500 )
    {
        g_kLastTime = kCurrentTime;
        return GAME_STATE_UPDATE;
    }
    return GAME_STATE_NOUPDATE;
}

int GetGameStatus(void)
{
    return g_nGameState;
}

void UpdateKeyState(void)
{
    if( MyKBHit() )
    {
        switch (MyGetCh())
        {
            case 97:    // a: LEFT
                g_nKeyDirX = -1;
                g_nKeyDirY = 0;
                break;
            case 100:   // d: RIGHT
                g_nKeyDirX = 1;
                g_nKeyDirY = 0;
                break;
            case 115:   // s: DOWN
                g_nKeyDirX = 0;
                g_nKeyDirY = 1;
                break;
            case 119:   // w: UP
                g_nKeyDirX = 0;
                g_nKeyDirY = -1;
                break;
            default:
                break;
        }
    }
}

void NewFood(void)
{
    int nX = rand() % MAX_WIDTH;
    int nY = rand() % MAX_HEIGHT;

    while( IsSnakeThere(nX, nY) != SNAKE_IS_NOT_THERE || g_arrGameMap[nY][nX] )
    {
        nX = rand() % MAX_WIDTH;
        nY = rand() % MAX_HEIGHT;
    }
    
    g_arrGameMap[nY][nX] = 2;
}